# -*- coding: utf-8 -*-
# Author: xiantingDeng
# File: run.py
# Time: 15:05

import multiprocessing
import os
from multiprocessing import Pool

import jprops
import pytest

from bin.config.environment import EnvironmentAndroid
from bin.utils.file_util import FilePath
from bin.utils.log_util import logger
from bin.utils.shell_util import Shell
from bin.utils.tool_util import ls_by_key


class Run:
    def __init__(self):
        self.file = FilePath()
        self.__log = logger
        self.device = EnvironmentAndroid(self.__log).equipment_information()

        # 定义测试报告路径
        self.xml_report_path = self.file.get_type_time_file("report", "xml")
        self.html_report_path = self.file.get_type_time_file("report", "html")
        self.properties_path = os.path.join(self.xml_report_path, 'environment.properties')

    def genrate_report(self):
        # 给报告添加执行环境信息
        env_properties = {}
        for i in self.device:
            for k, y in i.items():
                env_properties.update({k: y})
            break
        try:
            with open(self.properties_path, 'w', encoding='utf-8') as fp:
                jprops.store_properties(fp, env_properties)
                self.__log.info("环境信息已写入allure测试报告：{}".format(env_properties))
        except Exception as e:
            self.__log.error('配置环境未输出到报告中:{}'.format(e))

        # 执行生成报告命令
        cmd = 'allure generate %s -o %s --clean' % (self.xml_report_path, self.html_report_path)
        try:
            Shell.invoke(cmd)
            self.__log.info("allure测试报告生成：{}".format(self.html_report_path))
        except Exception as e:
            self.__log.error("Html测试报告生成失败,确保已经安装了Allure-Commandline：{}".format(e))

    def _scheduling_process(self):
        # 给多台设备分配测试任务的调度算法（简单平均调度）
        # 其中suit1是文件夹的名字、device1是配置中device设备的key

        """
        :return:
        {
        device1:[suit1,suit2]
        device2:[suit3,suit4]
        device3:[suit5]
        }
        """

        path = self.file.get_crm_path("case")
        suitname_list = ls_by_key(path, 'test_')

        if len(suitname_list) == 0 or len(self.device) == 0:
            raise IndexError('data is bad')

        scheduling_info = {}
        for i in self.device:
            scheduling_info[i["deviceName"]] = suitname_list

        self.__log.info("多设备分配的测试集执行为: {}\n".format(str(scheduling_info)))
        return scheduling_info

    def get_run_args(self, device_info):
        # 配置用于输出到报告的日志格式
        dir_tests = self.file.get_crm_path("case")
        args = ["-s", "-q", f"--cmdopt={device_info}", "--alluredir", self.xml_report_path, "--verbose"]
        for suit in self._scheduling_process().values():
            for i in suit:
                args.insert(2, os.path.join(dir_tests, i))
            break
        pytest.main(args)
        # print(args)

    def exec(self):
        try:
            self.__log.info('主进程开始:%s' % multiprocessing.current_process().name)

            with Pool(len(self.device)) as pool:
                pool.map(self.get_run_args, self.device)
                pool.close()
                pool.join()
        except Exception:
            raise ChildProcessError


if __name__ == '__main__':
    print(Run().exec())
